// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) 2006 Microsoft Corporation. All rights reserved.

// Original code from the Microsoft Windows SDK for Windows Vista.

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Xml;
using Microsoft.Feeds.Interop;

/// <summary>
/// Representation of an RSS element in a RSS 2.0 XML document.
/// </summary>
public class RssFeed : IItem
{
    private readonly string _title;
    private readonly string _link;
    private readonly string _description;
    private readonly string _path;
    private readonly DateTime _lastWriteTime;
    private List<RssItem> _items;

    public string Title { get { return this._title; } }
    public string Link { get { return this._link; } }
    public string Description { get { return this._description; } }
    public string Path { get { return this._path; } }
    public DateTime LastWriteTime { get { return this._lastWriteTime; } }
    public IList<RssItem> Items { get { return this._items.AsReadOnly(); } }

    /// <summary>
    /// Private constructor to be used with factory pattern.  
    /// </summary>
    /// <exception cref="System.Xml.XmlException">Occurs when the XML is not well-formed.</exception>
    /// <param name="xmlNode">An XML block containing the RSSFeed content.</param>
    private RssFeed(XmlNode xmlNode)
    {
        XmlNode channelNode = xmlNode.SelectSingleNode("rss/channel");
        this._items = new List<RssItem>();
        this._title = channelNode.SelectSingleNode("title").InnerText;
        this._link = channelNode.SelectSingleNode("link").InnerText;
        this._description = channelNode.SelectSingleNode("description").InnerText;

        XmlNodeList itemNodes = channelNode.SelectNodes("item");
        foreach (XmlNode itemNode in itemNodes)
        {
            RssItem rssItem = new RssItem(itemNode);
            
            // only add items that have enclosures.
            if (rssItem.Enclosure != null)
                this._items.Add(rssItem);
        }
    }

    private RssFeed(IFeed feed)
    {
        this._items = new List<RssItem>();
        this._title = feed.Title;
        this._link = feed.Link;
        this._description = feed.Description;
        this._path = feed.Path;
        this._lastWriteTime = feed.LastWriteTime;

        foreach (IFeedItem item in (IFeedsEnum)feed.Items)
        {
            RssItem rssItem =  new RssItem(item);

            // only add items that have enclosures.
            if (rssItem.Enclosure != null)
                this._items.Add(rssItem);
        } 
    }

    public static RssFeed FromUri(Uri uri)
    {
        XmlDocument xmlDoc;
        WebClient webClient = new WebClient();
        using (Stream rssStream = webClient.OpenRead(uri))
        {
            TextReader textReader = new StreamReader(rssStream);
            XmlTextReader reader = new XmlTextReader(textReader);
            xmlDoc = new XmlDocument();
            xmlDoc.Load(reader);
        }
        return new RssFeed(xmlDoc);
    }

    /// <summary>
    /// Factory to construct the RSSFeed object from the Windows RSS Platform API .
    /// </summary>
    /// <param name="feed">The Common Feed List feed object.</param>
    /// <returns>An initialized RSSFeed object.</returns>
    internal static RssFeed FromApi(IFeed feed)
    {
        RssFeed rssFeed = null;
        
        // Skip this feed if there are no items.
        if (feed != null
            && ((IFeedsEnum)feed.Items).Count > 0)
            rssFeed = new RssFeed(feed);
        return rssFeed;
    }

    /// <summary>
    /// Factory that constructs RssFeed objects from the text of an RSS 2.0 XML file.
    /// </summary>
    /// <param name="rssText">A string containing the XML for the RSS feed.</param>
    public static RssFeed FromText(string rssText)
    {
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.LoadXml(rssText);
        return new RssFeed(xmlDoc);
    }
}